#pragma once
#include <iostream>
#include <memory>
#include <string>
#include <jsoncpp/json/json.h>

static const std::string seg = "\r\n";

// len\r\n{jsonstr}\r\n
std::string Encode(const std::string &jsonstr)
{
    std::string strlen = std::to_string(jsonstr.size());
    return strlen + seg + jsonstr + seg;
}

std::string Decode(std::string &packagestream)
{
    // 报文完整性判断
    auto pos = packagestream.find(seg);
    if (pos == std::string::npos)
        return std::string();
    std::string lenstr = packagestream.substr(0, pos);
    int strlen = std::stoi(lenstr);
    int total = lenstr.size() + strlen + 2 * seg.size();
    if (packagestream.size() < total)
        return std::string();

    // 提取报文
    std::string jsonStr = packagestream.substr(pos + seg.size() + strlen);
    packagestream.erase(0, total);
    return jsonStr;
}

class Request
{
public:
    Request() {}

    Request(int x, int y, char oper)
        : _x(x), _y(y), _oper(oper) {}

    ~Request() {}

    bool Serialize(std::string &out)
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;
        Json::FastWriter writer;
        out = writer.write(root);
        return true;
    }

    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool res = reader.parse(in, root);
        if (!res)
            return false;
        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _oper = root["oper"].asInt();
        return true;
    }

    void Print()
    {
        std::cout << _x << std::endl;
        std::cout << _y << std::endl;
        std::cout << _oper << std::endl;
    }

    int X()
    {
        return _x;
    }

    int Y()
    {
        return _y;
    }

    char Oper()
    {
        return _oper;
    }

private:
    int _x;
    int _y;
    char _oper;
};

class Response
{
public:
    Response()
        : _result(0), _code(0), _desc("success") {}

    ~Response() {}

    bool Serialize(std::string &out)
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        root["desc"] = _desc;
        Json::FastWriter writer;
        out = writer.write(root);
        return true;
    }

    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool res = reader.parse(in, root);
        if (!res)
            return false;
        _result = root["result"].asInt();
        _code = root["code"].asInt();
        _desc = root["desc"].asCString();
        return true;
    }

    void Print()
    {
        if (!_code)
        {
            std::cout << _desc << std::endl;
        }
        else
        {
            std::cout << _result << std::endl;
        }
    }

public:
    int _result;
    int _code; // 0: success, 1: div zero 2. 非法操作
    std::string _desc;
};
